package com.stylefeng.guns.modular.assessment.calculate;

import com.stylefeng.guns.common.constant.factory.ConstantFactory;
import com.stylefeng.guns.common.constant.factory.IConstantFactory;
import com.stylefeng.guns.common.persistence.model.Assessment;
import com.stylefeng.guns.common.persistence.model.Indication;
import com.stylefeng.guns.common.persistence.model.ResourceData;
import com.stylefeng.guns.core.support.DateTimeKit;
import com.stylefeng.guns.core.util.DoubleUtil;
import com.stylefeng.guns.modular.assessment.calculate.exception.CalculateException;
import com.stylefeng.guns.modular.data.service.IResourceDataService;
import com.stylefeng.guns.modular.indication.service.IIndicationService;
import com.stylefeng.guns.modular.roadnet.service.IRoadnetService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.text.MessageFormat;
import java.text.ParseException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static com.stylefeng.guns.common.persistence.model.Assessment.WARNING_LEVEL_HIGH;
import static com.stylefeng.guns.core.support.DateTimeKit.NORM_DATE_PATTERN;

public abstract class ThirdIndicationCalculator extends IndicationCalculator {

    @Autowired
    protected IResourceDataService resourceDataService;

    @Autowired
    protected IIndicationService indicationService;

    @Autowired
	protected IRoadnetService roadnetService;

    public Assessment get(Integer roadnetId, Date beginDate, Date endDate) {
		Assessment assessment = calculate(roadnetId, beginDate, endDate);
        setWarningLevel(assessment);
        return assessment;
    }

    //设置风险等级
    private void setWarningLevel(Assessment assessment) {
        Indication indication = indicationService.selectById(getIndicationId());
        double thirdIndicationValue = assessment.getAssessmentValue();
        double max = indication.getMaxVal();
        double min = indication.getMinVal();
        if (indication.getBigIsBetter() == 1) {//越大越优
            if (thirdIndicationValue < min) {
                 assessment.setWarningLevel(WARNING_LEVEL_HIGH);
            }
        }else{
            if (thirdIndicationValue >= max) {
                assessment.setWarningLevel(WARNING_LEVEL_HIGH);
            }
        }
    }


    /**
     * 连续的分值计算
     *
     * @param roadnetId 车站id
     * @param beginDate 开始日期
     * @param startId   源数据类型开始id
     * @param endId     源数据类型结束id
     * @param baseScore 基础分值
     * @param increase  每次递增分值
     * @return
     */
    protected Double scoreCalculate(Integer roadnetId, Date beginDate, Date endDate, int startId, int endId, int baseScore, int increase) {
        double totalNum = 0d;
        double totalScore = 0d;
        for (int i = startId; i <= endId; i++) {
            //人数
            Double num = getDoubleValue(roadnetId, i, beginDate, endDate);
            totalScore = DoubleUtil.add(totalScore, DoubleUtil.mul(num, baseScore));
            totalNum = DoubleUtil.add(totalNum, num);

            baseScore += increase;
        }

        if (totalNum == 0d) {
            return 0d;
        }
        return DoubleUtil.div(totalScore, totalNum);
    }

    protected Double getDoubleValue(Integer roadnetId, Integer resourceDataTypeId, Date beginDate, Date endDate) {
		ResourceData resourceData = this.getResourceData(roadnetId, resourceDataTypeId, beginDate, endDate);
		return str2Double(resourceData.getValue());
	}

	@Deprecated
	protected Double getDoubleValue(List<ResourceData> resourceDataList) {
		if (CollectionUtils.isEmpty(resourceDataList)) {
			 throw new CalculateException("数据确实无法完成计算!");
		}
		return str2Double(resourceDataList.get(0).getValue());
	}


    protected List<Double> getMulDoubleValue(Integer roadnetId, Integer resourceDataTypeId, Date beginDate, Date endDate) {
        return getMulDoubleValue(roadnetId, resourceDataTypeId, beginDate, endDate, ',');
    }


    protected List<Double> getMulDoubleValue(Integer roadnetId, Integer resourceDataTypeId, Date beginDate, Date endDate, char delimiter) {
		ResourceData resourceData = this.getResourceData(roadnetId, resourceDataTypeId, beginDate, endDate);
		String[] values = StringUtils.split(resourceData.getValue(), delimiter);
		return Arrays.stream(values)
				.map(this::str2Double)
				.collect(Collectors.toList());
    }


	private ResourceData getResourceData(Integer roadnetId, Integer resourceDataTypeId, Date beginDate, Date endDate) {
		ResourceData resourceData = resourceDataService.selectUnique(roadnetId, resourceDataTypeId, beginDate, endDate);
		if (null == resourceData) {
			String roadnetName = ConstantFactory.me().getRoadnetNameById(roadnetId);
			String resourceDataTypeName = ConstantFactory.me().getResourceDataTypeNameById(resourceDataTypeId);
			String begeinDate = DateTimeKit.format(beginDate,NORM_DATE_PATTERN);
			String message = MessageFormat
					.format("数据缺失（时间:{0},地点:{1},数据类型:{2}），无法完成计算！", begeinDate, roadnetName, resourceDataTypeName);
			throw new CalculateException(message);
		}
		return resourceData;
	}

	protected double str2Double(String str)  {
		try {
			return  str.contains("%") ? DoubleUtil.formartPercent(str) : Double.valueOf(str);
		} catch (ParseException e) {
			throw new CalculateException("数据异常，不能完成计算");
		}
	}


	protected Integer getDurationT() {
        return 1440;
    }

}
